using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;

namespace Chat.Util
{
    public class Tools
    {
        static int headLength = 0;

        public static int HeadLength
        {
            get
            {
                if (headLength < 1)
                    headLength = Tools.GetStructLen<Head>(new Head());

                return headLength;
            }
        }

        public static IPAddress GetLocalIP()
        {
            //IPHostEntry ipHost = Dns.Resolve(Dns.GetHostName());
            //IPAddress ipAddr = ipHost.AddressList[0];
            //return ipAddr;

            string sHostName = Dns.GetHostName();
            IPHostEntry hostinfo = Dns.GetHostByName(sHostName);
            IPAddress add = hostinfo.AddressList[0];
            return add;
        }

        public static bool checkBoot(byte[] data)
        {
            if (data != null && data.Length > 2)
            {
                if (data[0] == Config.BOOT1 && data[1] == Config.BOOT2)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                return false;
            }
        }

        public static byte[] getBootBytes()
        {
            byte[] data = new byte[2];
            data[0] = Config.BOOT1;
            data[1] = Config.BOOT2;
            return data;
        }

        public static void addBootBytes(byte[] data)
        {
            byte[] boot = getBootBytes();
            Array.Copy(boot, 0, data, 0, 2);
        }

        public static void addBytes(byte[] a, byte[] b, int offset)
        {
            if (a != null && b != null)
            {
                if (b.Length >= a.Length)
                {
                    Array.Copy(a, 0, b, offset, a.Length);
                }
            }
        }

        public static byte[] getBytes(byte[] data, int index, int len)
        {
            byte[] temp = new byte[len];
            Array.Copy(data, index, temp, 0, len);
            return temp;
        }


        public static byte[] appendBytes(byte[] a, byte[] b)
        {
            if (a != null && b != null)
            {
                byte[] temp = new byte[a.Length + b.Length];
                addBytes(a, temp, 0);
                addBytes(b, temp, a.Length);
                return temp;
            }
            else
            {
                return null;
            }
        }

        public static byte[] getStringBytes(string str)
        {
            byte[] msg = Encoding.UTF8.GetBytes(str);
            return msg;
        }

        public static string getString(byte[] data)
        {
            string str =  Encoding.UTF8.GetString(data);
            return str.Replace("\0","");
        }

        public static byte[] getIntBytes(int num)
        {
            byte[] db = BitConverter.GetBytes(num);
            return db;
        }

        public static byte[] getIntBytes(UInt16 num)
        {
            byte[] db = BitConverter.GetBytes(num);
            return db;
        }

        public static int getUInt16(byte[] data)
        {
            ushort iLen = 0;
            if (data != null && data.Length == 2)
            {
                iLen = BitConverter.ToUInt16(data, 0);
            }
            if (iLen < 0)
            {
                iLen = 0;
            }
            return iLen;
        }

        
        public static int getInt(byte[] data)
        {
            int iLen = 0;
            if(data!=null&&data.Length==4){
                iLen = BitConverter.ToInt32(data, 0);
            }
            if (iLen < 0)
            {
                iLen = 0;
            }
            return iLen;
        }

        public static byte[] getIpBytes(string ip)
        {
            try
            {
                IPAddress ipa = IPAddress.Parse(ip);
                return getIpBytes(ipa);
            }
            catch { return null; }
        }

        public static byte[] getIpBytes(IPAddress ipa)
        {
            if (ipa != null)
            {
                return ipa.GetAddressBytes();
            }
            else 
            {
                return null;
            }
        }

        public static string getIp(byte[] bIp)
        {
            string sIp = "0.0.0.0";
            if (bIp != null && bIp.Length == 4)
            {
                sIp = Convert.ToString(bIp[0]) + "." + Convert.ToString(bIp[1]) + "." + Convert.ToString(bIp[2]) + "." + Convert.ToString(bIp[3]);
            }
            return sIp;
        }


        public static string getUserId(int index)
        {
            return Config.ID_START + index.ToString();
        }

        

        public static string getSystemId()
        {
            return Config.SYS_ID;
        }

        public static byte[] getHeadBytes(Head h)
        {
            h.boot = getBootBytes();
            if (h.ip[0]!=0)
            {
                h.ip = GetLocalIP().ToString();
            }
            if (h.len < 0)
            {
                h.len = 0;
            }
            if (h.port == 0)
            {
                h.port = Config.ServerPort;
            }
            return Tools.StructToBytes(h);
        }

        public static Head getHead(byte[] data)
        {
            if (data.Length >= HeadLength)
            {
                MemoryStream stream = new MemoryStream();
                stream.Write(data, 0, HeadLength);
                return Tools.BytesToStruct<Head>(stream.ToArray());
            }
            return new Head();
        }

        public static byte[] getHeadBytes(byte[] data)
        {
            return getBytes(data, 0, Config.HEAD_SIZE);
        }


        public static byte[] getBodyBytes(byte[] data,int len)
        {
            return getBytes(data, Config.HEAD_SIZE, len);
        }


        public static string getDateTime()
        {
            DateTime dt = System.DateTime.Now;
            return dt.ToString("yyyy-MM-dd HH:mm:ss");
        }



        public static byte[] StructToBytes<T>(T obj)
        {
            int size = Marshal.SizeOf(obj);
            byte[] bytes = new byte[size];
            IntPtr arrPtr = Marshal.UnsafeAddrOfPinnedArrayElement(bytes, 0);
            Marshal.StructureToPtr(obj, arrPtr, true);
            return bytes;
        }

        public static T BytesToStruct<T>(byte[] bytes)
        {
            IntPtr arrPtr = Marshal.UnsafeAddrOfPinnedArrayElement(bytes, 0);
            return (T)Marshal.PtrToStructure(arrPtr, typeof(T));
        }


        public static int GetStructLen<T>(T obj)
        {
            int len = Marshal.SizeOf(obj);
            return len;
        }


    }
}
